package com.Pawtrack.info.utils;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.Pawtrack.common.utils.DateUtils;

/**
 * 重复提醒工具类
 * 
 * @author ruoyi
 * @date 2025-08-14
 */
public class RepeatRuleUtils
{
    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 重复规则类型
     */
    public static final String TYPE_DAILY = "daily";
    public static final String TYPE_WEEKLY = "weekly";
    public static final String TYPE_MONTHLY = "monthly";
    public static final String TYPE_YEARLY = "yearly";
    public static final String TYPE_CUSTOM = "custom";

    /**
     * 创建每日重复规则
     * 
     * @param interval 间隔天数
     * @return 重复规则JSON字符串
     */
    public static String createDailyRule(int interval)
    {
        Map<String, Object> rule = new HashMap<>();
        rule.put("type", TYPE_DAILY);
        rule.put("interval", interval);
        return toJsonString(rule);
    }

    /**
     * 创建每周重复规则
     * 
     * @param interval 间隔周数
     * @param days 每周的天数（0=周日, 1=周一, ..., 6=周六）
     * @return 重复规则JSON字符串
     */
    public static String createWeeklyRule(int interval, Integer[] days)
    {
        Map<String, Object> rule = new HashMap<>();
        rule.put("type", TYPE_WEEKLY);
        rule.put("interval", interval);
        rule.put("days", days);
        return toJsonString(rule);
    }

    /**
     * 创建每月重复规则
     * 
     * @param interval 间隔月数
     * @param days 每月的日期（1-31）
     * @return 重复规则JSON字符串
     */
    public static String createMonthlyRule(int interval, Integer[] days)
    {
        Map<String, Object> rule = new HashMap<>();
        rule.put("type", TYPE_MONTHLY);
        rule.put("interval", interval);
        rule.put("days", days);
        return toJsonString(rule);
    }

    /**
     * 创建每年重复规则
     * 
     * @param interval 间隔年数
     * @param months 每年的月份（1-12）
     * @param days 每月的日期（1-31）
     * @return 重复规则JSON字符串
     */
    public static String createYearlyRule(int interval, Integer[] months, Integer[] days)
    {
        Map<String, Object> rule = new HashMap<>();
        rule.put("type", TYPE_YEARLY);
        rule.put("interval", interval);
        rule.put("months", months);
        rule.put("days", days);
        return toJsonString(rule);
    }

    /**
     * 创建自定义重复规则
     * 
     * @param days 每周的天数（0=周日, 1=周一, ..., 6=周六）
     * @return 重复规则JSON字符串
     */
    public static String createCustomRule(Integer[] days)
    {
        Map<String, Object> rule = new HashMap<>();
        rule.put("type", TYPE_CUSTOM);
        rule.put("days", days);
        return toJsonString(rule);
    }

    /**
     * 计算下次触发日期
     * 
     * @param repeatRule 重复规则JSON字符串
     * @param lastTriggeredDate 上次触发日期
     * @param repeatEndDate 重复结束日期
     * @return 下次触发日期，如果超过结束日期则返回null
     */
    public static Date calculateNextTriggerDate(String repeatRule, Date lastTriggeredDate, Date repeatEndDate)
    {
        if (repeatRule == null || repeatRule.isEmpty()) {
            return null;
        }

        try {
            JsonNode ruleNode = objectMapper.readTree(repeatRule);
            String type = ruleNode.has("type") ? ruleNode.get("type").asText() : TYPE_DAILY;
            int interval = ruleNode.has("interval") ? ruleNode.get("interval").asInt() : 1;

            Calendar calendar = Calendar.getInstance();
            calendar.setTime(lastTriggeredDate);

            switch (type) {
                case TYPE_DAILY:
                    calendar.add(Calendar.DAY_OF_MONTH, interval);
                    break;
                case TYPE_WEEKLY:
                    calendar.add(Calendar.WEEK_OF_YEAR, interval);
                    break;
                case TYPE_MONTHLY:
                    calendar.add(Calendar.MONTH, interval);
                    break;
                case TYPE_YEARLY:
                    calendar.add(Calendar.YEAR, interval);
                    break;
                case TYPE_CUSTOM:
                    if (ruleNode.has("days") && ruleNode.get("days").isArray()) {
                        // 找到下一个匹配的日期
                        calendar.add(Calendar.DAY_OF_MONTH, 1);
                        while (!shouldGenerateInstance(repeatRule, calendar.getTime())) {
                            calendar.add(Calendar.DAY_OF_MONTH, 1);
                        }
                    }
                    break;
                default:
                    calendar.add(Calendar.DAY_OF_MONTH, 1);
            }

            // 检查是否超过结束日期
            if (repeatEndDate != null && calendar.getTime().after(repeatEndDate)) {
                return null;
            }

            return calendar.getTime();

        } catch (Exception e) {
            // 解析JSON失败，使用默认的每日重复
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(lastTriggeredDate);
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            
            if (repeatEndDate != null && calendar.getTime().after(repeatEndDate)) {
                return null;
            }
            
            return calendar.getTime();
        }
    }

    /**
     * 检查指定日期是否应该生成实例
     * 
     * @param repeatRule 重复规则JSON字符串
     * @param targetDate 目标日期
     * @return 是否应该生成
     */
    public static boolean shouldGenerateInstance(String repeatRule, Date targetDate)
    {
        if (repeatRule == null || repeatRule.isEmpty()) {
            return false;
        }

        try {
            JsonNode ruleNode = objectMapper.readTree(repeatRule);
            String type = ruleNode.has("type") ? ruleNode.get("type").asText() : TYPE_DAILY;

            Calendar targetCal = Calendar.getInstance();
            targetCal.setTime(targetDate);
            int dayOfWeek = targetCal.get(Calendar.DAY_OF_WEEK) - 1; // 0=周日, 1=周一, ..., 6=周六
            int dayOfMonth = targetCal.get(Calendar.DAY_OF_MONTH);
            int month = targetCal.get(Calendar.MONTH) + 1; // 1-12

            switch (type) {
                case TYPE_DAILY:
                    return true;
                case TYPE_WEEKLY:
                    if (ruleNode.has("days") && ruleNode.get("days").isArray()) {
                        JsonNode daysNode = ruleNode.get("days");
                        for (JsonNode dayNode : daysNode) {
                            if (dayNode.asInt() == dayOfWeek) {
                                return true;
                            }
                        }
                        return false;
                    }
                    return true; // 默认每周都提醒
                case TYPE_MONTHLY:
                    if (ruleNode.has("days")) {
                        JsonNode daysNode = ruleNode.get("days");
                        for (JsonNode dayNode : daysNode) {
                            if (dayNode.asInt() == dayOfMonth) {
                                return true;
                            }
                        }
                        return false;
                    }
                    return true; // 默认每月都提醒
                case TYPE_YEARLY:
                    if (ruleNode.has("months") && ruleNode.has("days")) {
                        JsonNode monthsNode = ruleNode.get("months");
                        JsonNode daysNode = ruleNode.get("days");
                        
                        for (JsonNode monthNode : monthsNode) {
                            if (monthNode.asInt() == month) {
                                for (JsonNode dayNode : daysNode) {
                                    if (dayNode.asInt() == dayOfMonth) {
                                        return true;
                                    }
                                }
                            }
                        }
                        return false;
                    }
                    return true; // 默认每年都提醒
                case TYPE_CUSTOM:
                    if (ruleNode.has("days") && ruleNode.get("days").isArray()) {
                        JsonNode daysNode = ruleNode.get("days");
                        for (JsonNode dayNode : daysNode) {
                            if (dayNode.asInt() == dayOfWeek) {
                                return true;
                            }
                        }
                    }
                    return false;
                default:
                    return true;
            }
        } catch (Exception e) {
            return true; // 解析失败，默认生成
        }
    }

    /**
     * 解析重复规则
     * 
     * @param repeatRule 重复规则JSON字符串
     * @return 重复规则的Map表示
     */
    public static Map<String, Object> parseRepeatRule(String repeatRule)
    {
        try {
            JsonNode ruleNode = objectMapper.readTree(repeatRule);
            Map<String, Object> rule = new HashMap<>();
            
            if (ruleNode.has("type")) {
                rule.put("type", ruleNode.get("type").asText());
            }
            if (ruleNode.has("interval")) {
                rule.put("interval", ruleNode.get("interval").asInt());
            }
            if (ruleNode.has("days") && ruleNode.get("days").isArray()) {
                JsonNode daysNode = ruleNode.get("days");
                Integer[] days = new Integer[daysNode.size()];
                for (int i = 0; i < daysNode.size(); i++) {
                    days[i] = daysNode.get(i).asInt();
                }
                rule.put("days", days);
            }
            if (ruleNode.has("months") && ruleNode.get("months").isArray()) {
                JsonNode monthsNode = ruleNode.get("months");
                Integer[] months = new Integer[monthsNode.size()];
                for (int i = 0; i < monthsNode.size(); i++) {
                    months[i] = monthsNode.get(i).asInt();
                }
                rule.put("months", months);
            }
            
            return rule;
        } catch (Exception e) {
            return new HashMap<>();
        }
    }

    /**
     * 格式化重复规则为可读字符串
     * 
     * @param repeatRule 重复规则JSON字符串
     * @return 可读的重复规则描述
     */
    public static String formatRepeatRule(String repeatRule)
    {
        Map<String, Object> rule = parseRepeatRule(repeatRule);
        String type = (String) rule.get("type");
        
        if (type == null) {
            return "不重复";
        }
        
        switch (type) {
            case TYPE_DAILY:
                int dailyInterval = (Integer) rule.getOrDefault("interval", 1);
                return dailyInterval == 1 ? "每天" : "每" + dailyInterval + "天";
            case TYPE_WEEKLY:
                int weeklyInterval = (Integer) rule.getOrDefault("interval", 1);
                Integer[] days = (Integer[]) rule.get("days");
                if (days != null && days.length > 0) {
                    String[] dayNames = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
                    StringBuilder sb = new StringBuilder();
                    for (int day : days) {
                        if (sb.length() > 0) {
                            sb.append(", ");
                        }
                        sb.append(dayNames[day]);
                    }
                    return (weeklyInterval == 1 ? "每周" : "每" + weeklyInterval + "周") + "的" + sb.toString();
                }
                return weeklyInterval == 1 ? "每周" : "每" + weeklyInterval + "周";
            case TYPE_MONTHLY:
                int monthlyInterval = (Integer) rule.getOrDefault("interval", 1);
                Integer[] monthDays = (Integer[]) rule.get("days");
                if (monthDays != null && monthDays.length > 0) {
                    StringBuilder sb = new StringBuilder();
                    for (int day : monthDays) {
                        if (sb.length() > 0) {
                            sb.append(", ");
                        }
                        sb.append(day + "日");
                    }
                    return (monthlyInterval == 1 ? "每月" : "每" + monthlyInterval + "个月") + "的" + sb.toString();
                }
                return monthlyInterval == 1 ? "每月" : "每" + monthlyInterval + "个月";
            case TYPE_YEARLY:
                int yearlyInterval = (Integer) rule.getOrDefault("interval", 1);
                Integer[] months = (Integer[]) rule.get("months");
                Integer[] yearDays = (Integer[]) rule.get("days");
                if (months != null && yearDays != null && months.length > 0 && yearDays.length > 0) {
                    String[] monthNames = {"1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"};
                    StringBuilder sb = new StringBuilder();
                    for (int month : months) {
                        if (sb.length() > 0) {
                            sb.append(", ");
                        }
                        sb.append(monthNames[month - 1]);
                    }
                    sb.append("的");
                    for (int day : yearDays) {
                        if (sb.indexOf("的") < sb.length() - 1) {
                            sb.append(", ");
                        }
                        sb.append(day + "日");
                    }
                    return (yearlyInterval == 1 ? "每年" : "每" + yearlyInterval + "年") + "的" + sb.toString();
                }
                return yearlyInterval == 1 ? "每年" : "每" + yearlyInterval + "年";
            case TYPE_CUSTOM:
                Integer[] customDays = (Integer[]) rule.get("days");
                if (customDays != null && customDays.length > 0) {
                    String[] dayNames = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
                    StringBuilder sb = new StringBuilder("自定义：每周的");
                    for (int day : customDays) {
                        if (sb.length() > 7) {
                            sb.append(", ");
                        }
                        sb.append(dayNames[day]);
                    }
                    return sb.toString();
                }
                return "自定义";
            default:
                return "不重复";
        }
    }

    /**
     * 将Map转换为JSON字符串
     * 
     * @param rule 规则Map
     * @return JSON字符串
     */
    private static String toJsonString(Map<String, Object> rule)
    {
        try {
            return objectMapper.writeValueAsString(rule);
        } catch (Exception e) {
            return "{}";
        }
    }
}